<?php


namespace app\push\controller;

use app\common\library\Token;
use app\common\model\Blacklist;
use app\common\model\ClientUser;
use app\common\model\Room;
use app\common\model\RoomChat;
use app\common\model\RoomUser;
use app\common\model\User;
use app\common\model\UserChat;
use app\common\model\UserChatGroup;
use GatewayWorker\Lib\Gateway;
use think\Exception;
use think\Validate;
use think\worker\Server;

class Worker extends Server{

    private static function checkAuth($message_data){
        if(!isset($message_data['token']) || empty($message_data['token'])){
            throw new \Exception('请登陆后操作');
        }
        $data = Token::get($message_data['token']);
        if (!$data) {
            write_log($message_data['token'],'workerman长连接token错误');
            throw new \Exception('请登陆后操作');
        }
        $user_id = intval($data['user_id']);
        return $user_id;
    }

    /**
     * 有消息时
     * @param int $client_id
     * @param mixed $message
     */
    public static function onMessage($client_id, $message)
    {
        try{
            //echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']}  client_id:$client_id session:".json_encode($_SESSION)." onMessage:".$message."\n";

            // 客户端传递的是json数据
            $message_data = json_decode($message, true);
            if(!$message_data)
            {
                return ;
            }

            // 验证token
            $user_id = self::checkAuth($message_data);
            $user = User::where('id',$user_id)->field('id,nickname,level,avatar,education')->find();
            if(empty($user)){
                throw new \Exception('用户不存在');
            }
            $message_data['user'] = $user;
            // 根据类型执行不同的业务
            switch($message_data['type'])
            {
                // 客户端回应服务端的心跳
                case 'pong':
                    return;
                // 客户端登录 绑定uid
                // message格式: {type:login, token:"xxxxx"}
                case 'login':
                    self::userLogin($client_id,$message_data);
                    break;
                // 客户端发言 (私聊)
                // message: {type:say, to_client_id:xx, content:xx}
                case 'say':
                    self::sendMsg($message_data);
                    break;
                case 'group':
                    self::userGroup($message_data);
                    break;
            }
            return ;
        }catch(\Exception $e){
            // 错误处理
            $new_message = array(
                'type'      =>'error',
                'content'   => $e->getMessage(),
                'time'      =>date('Y-m-d H:i:s'),
            );
            Gateway::sendToCurrentClient(json_encode($new_message));
            return ;
        }
    }

    /**
     * 当客户端断开连接时
     * @param integer $client_id 客户端id
     */
    public static function onClose($client_id)
    {
        ClientUser::where('client_id',$client_id)->delete();
    }


    private static function userLogin($client_id,$message_data){
        $user = $message_data['user'];

        $count = ClientUser::where('user_id',$user['id'])->count();
        if($count > 0){
            ClientUser::where('user_id',$user['id'])->delete();
        }
        // 添加客户端连接信息
        ClientUser::create([
            'user_id'   => $user['id'],
            'client_id' => $client_id,
        ]);

        // 转播给当前房间的所有客户端，xx进入聊天室 message {type:login, client_id:xx, name:xx}
        //$new_message = array('type'=>$message_data['type'], 'client_id'=>$client_id, 'user'=>$user, 'time'=>date('Y-m-d H:i:s'));
        //$client = ClientUser::all();
        //foreach($client as $v){
        //    $new_message['client_list'][$v['client_id']] = User::where('id',$v['user_id'])->field('id,nickname,level,avatar')->find();
        //}
        //Gateway::sendToCurrentClient(json_encode($new_message));
        return;
    }

    private static function sendMsg($message_data){
        $validate = new Validate([
            'to_user_id'=> 'require',
            'msg_type'  => 'require|in:1,2,3'
        ],[
            'to_user_id'=> '参数错误',
            'msg_type'  => '参数错误'
        ]);
        if (!$validate->check($message_data)) {
            throw new \Exception($validate->getError());
        }
        $user = $message_data['user'];

        $blackList = Blacklist::where('user_id',$message_data['to_user_id'])->where('to_user_id',$user['id'])->count();
        if($blackList > 0){
            throw new Exception('对方把你拉黑，无法发送消息');
        }
        $content = nl2br(htmlspecialchars($message_data['content']));

        $new_message = array(
            'type'      =>'say',
            'user'      => $user,
            'to_user_id'=> $message_data['to_user_id'],
            'content'   => $content,
            'msg_type'  => $message_data['msg_type'],
            'time'      =>date('Y-m-d H:i:s'),
        );

        // 插叙聊天分组是否存在
        $count = UserChatGroup::where(function($query) use($message_data){
            $query->where('user_id',$message_data['user']['id'])->where('to_user_id',$message_data['to_user_id']);
        })->whereOr(function($query) use($message_data){
            $query->where('to_user_id',$message_data['user']['id'])->where('user_id',$message_data['to_user_id']);
        })->count();
        if($count < 1){
            $result = UserChatGroup::create([
                'user_id'   => $user['id'],
                'to_user_id'=> $message_data['to_user_id'],
            ]);
            $groupId = $result->id;
        }else{
            $groupId = UserChatGroup::where(function($query) use($message_data){
                $query->where('user_id',$message_data['user']['id'])->where('to_user_id',$message_data['to_user_id']);
            })->whereOr(function($query) use($message_data){
                $query->where('to_user_id',$message_data['user']['id'])->where('user_id',$message_data['to_user_id']);
            })->value('id');
        }

        UserChat::create([
            'user_id'    => $user['id'],
            'to_user_id' => $message_data['to_user_id'],
            'content'    => $content,
            'msg_type'   => $message_data['msg_type'],
            'group_id'   => $groupId,
        ]);

        $toClientId = ClientUser::where('user_id',$message_data['to_user_id'])->value('client_id');
        if(!empty($toClientId)){
            Gateway::sendToClient($toClientId, json_encode($new_message));
        }
        Gateway::sendToCurrentClient(json_encode($new_message));
        return true;
    }


    /**
     * 处理群消息
     * @param $message_data
     * @return bool
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private static function userGroup($message_data){
        $validate = new Validate([
            'room_id'   => 'require',
            'msg_type'  => 'require|in:1,2,3'
        ],[
            'room_id'   => '参数错误',
            'msg_type'  => '参数错误'
        ]);
        if (!$validate->check($message_data)) {
            throw new \Exception($validate->getError());
        }

        $user = $message_data['user'];

        $roomInfo = Room::where('id',$message_data['room_id'])->find();
        if(empty($roomInfo)){
            throw new \Exception('参数错误');
        }
        $count = RoomUser::where('user_id',$user['id'])->where('room_id',$message_data['room_id'])->find();
        if(empty($count)){
            throw new \Exception('家族不存在');
        }
        if($count['status'] != 1){
            throw new \Exception('您已被禁言，无法发送消息');
        }

        $content = nl2br(htmlspecialchars($message_data['content']));
        $new_message = array(
            'type'      => 'group',
            'user'      => $user,
            'room_id'   => $message_data['room_id'],
            'content'   => $content,
            'msg_type'  => $message_data['msg_type'],
            'time'      => date('Y-m-d H:i:s'),
        );
        $sendMsg = json_encode($new_message);
        Gateway::sendToCurrentClient($sendMsg);
        $uid = RoomUser::where('room_id',$roomInfo['id'])->column('user_id');
        $uid = array_diff($uid,[$user['id']]);
        $clients = ClientUser::where('user_id','IN',$uid)->column('client_id');
        foreach($clients as $v){
            Gateway::sendToClient($v,$sendMsg);
        }
        RoomChat::create([
            'user_id'   => $user['id'],
            'content'   => $content,
            'msg_type'  => $message_data['msg_type'],
            'room_id'   => $message_data['room_id']
        ]);
        return true;
    }
}